home *** CD-ROM | disk | FTP | other *** search
/ Assassins - Ultimate CD Games Collection 2 / Assassins 2 - Ultimate Games No. 2 (1995)(Weird Science)[!][Amiga-CD32-CDTV].iso / arcade / moon_rocks_aga / game.c < prev    next >
C/C++ Source or Header  |  1995-01-01  |  34KB  |  1,270 lines

  1. /*
  2.  * MOON ROCKS by Alan Bland.  This is an example game using the
  3.  * GameSmith Development System.  You are free to use portions of
  4.  * this source code for any purpose whatsoever.  This isn't
  5.  * necessarily the best way to use GDS for this type of game,
  6.  * but it shows usage of many of the components of GDS (anims,
  7.  * anim complexes, sounds, scrolling background, multiple viewports,
  8.  * RastPort usage, background collision detection).
  9.  *
  10.  * This game won't work on an OCS Amiga because of the large
  11.  * scrolling superbitmap.  It may also require 1 meg of chip ram.
  12.  *
  13.  * The elvis animation is based on the "tiny elvis" public domain
  14.  * screen hack for Microsoft Windows.  I changed it around quite
  15.  * a bit to reduce the color palette and to make different dancing
  16.  * motions from the original.
  17.  *
  18.  * Call CYBERMIGA BBS at 1-303-939-9923.  Lots of Amiga files!
  19.  */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <fcntl.h>
  25. #include <math.h>
  26. #include <intuition/intuition.h>
  27. #include <exec/memory.h>
  28. #include <exec/types.h>
  29. #include <graphics/gfx.h>
  30. #include <graphics/gfxbase.h>
  31.  
  32. #include <clib/exec_protos.h>
  33. #include <clib/graphics_protos.h>
  34. #include <clib/intuition_protos.h>
  35.  
  36. #include "GameSmith:GameSmith.h"
  37. #include "GameSmith:include/libraries/libptrs.h"
  38. #include "GameSmith:include/proto/all_regargs.h"
  39.  
  40. /* header file for anim complexes */
  41. #include "lc.h"
  42. #include "rs.h"
  43.  
  44. #define DDEPTH  3
  45. #define NUM_COLORS 8
  46.  
  47. #define VP2_HEIGHT 19
  48. #define VP2_DEPTH 3
  49. #define VP2_NUM_COLORS 8
  50.  
  51. #define DWIDTH 320
  52. #define DHEIGHT (200-VP2_HEIGHT-3)
  53. #define DISP_MODE 0
  54.  
  55. #define X_SCROLLPOS (DWIDTH/3)
  56. #define Y_SCROLLTOP (DHEIGHT/4)
  57. #define Y_SCROLLBOT (DHEIGHT/2)
  58.  
  59. /* this defines the vertical position below which the spacecraft
  60.  * can collide with background objects.  see main loop comments.
  61.  */
  62. #define GROUND_THRESHOLD (bmheight-52)
  63.  
  64. /* this is how close (pixels) we must land to the target to win the game */
  65. #define CLOSE_ENOUGH 250
  66.  
  67. #define MAX_FUEL 3000
  68. #define LOW_FUEL 300
  69.  
  70. /* physical constants */
  71. #define MAX_ALTITUDE 70000.0
  72. #define MAX_RANGE 50000.0
  73. #define GRAVITY 5.0
  74. #define THRUST 10.0
  75. #define SAFE_SPEED 200.0
  76.  
  77. /* To be strictly accurate, I think this should be 60 for NTSC, 50 for PAL */
  78. #define TICKS_PER_SEC 60
  79.  
  80. /* joystick responsiveness - set to 0 for fastest */
  81. #define JOY_INTERVAL 3
  82.  
  83. /* how often to animate the rock star */
  84. #define DANCE_DELAY 5
  85. unsigned char time_to_dance;
  86. short dance_time;
  87. unsigned char rockstar_visible;   /* is he visible? */
  88. unsigned long rockstar_time;      /* next time that he changes animation */
  89. unsigned char allow_rockstar;     /* allow him to materialize */
  90. /*
  91.  * The VP2 bitmap has several different control panel images which we
  92.  * scroll into view as necessary.  The top image is the normal panel.
  93.  * These constants define the scroll offset for each image.
  94.  */
  95. #define VP_PAUSED  VP2_HEIGHT
  96. #define VP_NOWHERE (VP2_HEIGHT*2)
  97. #define VP_VISIBLE (VP2_HEIGHT*3)
  98. #define VP_CRASHED (VP2_HEIGHT*4)
  99. #define VP_SUCCESS (VP2_HEIGHT*5)
  100.  
  101.  
  102. unsigned long lunar_cmap[NUM_COLORS];
  103. unsigned long vp2_cmap[VP2_NUM_COLORS];
  104.  
  105. /* need a copper list to turn off sprites */
  106. unsigned short copper_list[] = {
  107.     UC_WAIT, 0, 0, UC_NOSPRITES, UC_END
  108. };
  109.  
  110. struct copper_struct copper = 
  111.     {
  112.     copper_list,
  113.     NULL,
  114.     NULL
  115.     };
  116. /*
  117.  * vp is the viewport for the main viewing area.
  118.  * vp2 is the control panel at the bottom of the screen.
  119.  */
  120.  
  121. struct gs_viewport vp2 = {
  122.     NULL,                /* ptr to next viewport */
  123.     vp2_cmap,                /* ptr to color table */
  124.     VP2_NUM_COLORS,            /* number of colors in table */
  125.     &copper,                /* ptr to user copper list */
  126.     VP2_HEIGHT,DWIDTH,VP2_DEPTH,    /* height, width, depth */
  127.     0,0,                /* bmheight, bmwidth */
  128.     DHEIGHT+2,0,            /* top & left viewport offsets */
  129.     0,0,                /* X & Y bitmap offsets */
  130.     0,                    /* flags */
  131.     NULL,NULL,                /* 2.xx & above compatibility stuff */
  132.     NULL,NULL,                /* bitmap pointers */
  133.     NULL,                /* future expansion */
  134.     0,0,0,0                /* display clip (use nominal) */
  135. };
  136.  
  137. struct gs_viewport vp = {
  138.     &vp2,                /* ptr to next viewport */
  139.     lunar_cmap,                /* ptr to color table */
  140.     NUM_COLORS,                /* number of colors in table */
  141.     NULL,                /* ptr to user copper list */
  142.     DHEIGHT,DWIDTH,DDEPTH,        /* height, width, depth */
  143.     0,0,                /* bmheight, bmwidth */
  144.     0,0,                /* top & left viewport offsets */
  145.     0,0,                /* X & Y bitmap offsets */
  146.     0,                    /* flags */
  147.     NULL,NULL,                /* 2.xx & above compatibility stuff */
  148.     NULL,NULL,                /* bitmap pointers */
  149.     NULL,                /* future expansion */
  150.     0,0,0,0                /* display clip (use nominal) */
  151. };
  152.  
  153. struct display_struct lunar_display = {
  154.     NULL,                /* ptr to previous display view */
  155.     NULL,NULL,                /* 2.xx & above compatibility stuff */
  156.     0,0,                /* X and Y display offsets (1.3 style) */
  157.     DISP_MODE,                /* display mode ID */
  158.     GSV_DOUBLE|GSV_SCROLLABLE,        /* flags (double buffered, scrollable) */
  159.     &vp,                /* ptr to 1st viewport */
  160.     NULL                /* future expansion */
  161. };
  162.  
  163. struct anim_cplx *lem;            /* the spacecraft anim complex */
  164. struct anim_cplx *rockstar;             /* the rock star anim complex */
  165. struct display_struct *display;        /* points at lunar_display if it got created ok */
  166. struct Interrupt *scroller=NULL;    /* interrupt handler for smooth scrolling */
  167. int dlist=-1;                /* display list used with anim system */
  168. int bmwidth;
  169. int bmheight;
  170. struct RastPort rp;            /* RastPort for writing text to the control panel */
  171. struct BitMap *cp_bitmaps[2];        /* need to double-buffer bitmaps for RastPort */
  172. struct TextAttr sysfont = {        /* control panel will be topaz.8 */
  173.    "topaz.font", 8, 0, 0
  174. };
  175. struct TextFont *myfont;
  176.  
  177. short elapsed_mins;
  178. short elapsed_secs;
  179. short elapsed_ticks;
  180.  
  181. /*
  182.  * The MED module uses channels 0 and 1.  Sound effects are on 2 and 3
  183.  * except for the PING sound, which is only played without music so it's
  184.  * on one of the music channels.
  185.  */
  186. #include "libproto.h"
  187. struct MMD0 *tune;
  188. struct Library *MEDPlayerBase;
  189.    
  190. /*
  191.  * structures and channel assignments for each sound.
  192.  */
  193. #define THRUST_CHANNEL CHANNEL2
  194. #define WHOOP_CHANNEL  CHANNEL3
  195. #define PING_CHANNEL   CHANNEL1
  196. #define FILL_CHANNEL   CHANNEL3
  197. #define KABOOM_CHANNEL CHANNEL2
  198. #define LANDED_CHANNEL CHANNEL3
  199.  
  200. struct sound_struct thrust;
  201. struct sound_struct whoop;
  202. struct sound_struct kaboom;
  203. struct sound_struct landed;
  204. struct sound_struct ping;
  205. struct sound_struct fill;
  206.  
  207. /* the "lc" anim complex contains zillions of short anims showing the
  208.    spacecraft at various rotation angles (increments of 15 degrees),
  209.    with and without flames. the "lc_flame" array lists the anims with
  210.    flames in clockwise rotation order.  "lc_noflame" lists the anims
  211.    without flames. */
  212.  
  213. #define LC_ANIM_COUNT 24
  214.  
  215. short lc_flame[LC_ANIM_COUNT] = {
  216. FLAME00, FLAME15, FLAME30, FLAME45, FLAME60, FLAME75,
  217. FLAME90, FLAME105, FLAME120, FLAME135, FLAME150, FLAME165,
  218. FLAME180, FLAME195, FLAME210, FLAME225, FLAME240, FLAME255,
  219. FLAME270, FLAME285, FLAME300, FLAME315, FLAME330, FLAME345
  220. };
  221. short lc_noflame[LC_ANIM_COUNT] = {
  222. LEM00, LEM15, LEM30, LEM45, LEM60, LEM75,
  223. LEM90, LEM105, LEM120, LEM135, LEM150, LEM165,
  224. LEM180, LEM195, LEM210, LEM225, LEM240, LEM255,
  225. LEM270, LEM285, LEM300, LEM315, LEM330, LEM345
  226. };
  227.  
  228. /* sines and cosines are pre-computed for each 15 degree rotational
  229.    position.  this makes the game fast enough to run on an old
  230.    68000 Amiga without a math chip. */
  231.  
  232. double sinval[LC_ANIM_COUNT] = {
  233. -1.000000, -0.966168, -0.866519, -0.707840, -0.500941, -0.259916,
  234. 0.000000, 0.258771, 0.499914, 0.707002, 0.865927, 0.965862,
  235. 1.000000, 0.966015, 0.866223, 0.707421, 0.500428, 0.259344,
  236. 0.000593, -0.258199, -0.499401, -0.706583, -0.865630, -0.965708
  237. };
  238.  
  239. double cosval[LC_ANIM_COUNT] = {
  240. -0.000889, 0.257913, 0.499144, 0.706373, 0.865482, 0.965631,
  241. 1.000000, 0.965939, 0.866075, 0.707212, 0.500171, 0.259058,
  242. 0.000296, -0.258485, -0.499658, -0.706792, -0.865778, -0.965785,
  243. -1.000000, -0.966092, -0.866371, -0.707630, -0.500684, -0.259630
  244. };
  245.  
  246.  
  247. /* The "craft" structure defines the current physical attributes of
  248.    the spacecraft. */
  249.  
  250. struct {
  251.     int fuel;        /* fuel remaining */
  252.     int index;       /* array index into lc_flame/lc_noflame which indicates
  253.             the current rotation of the spacecraft */
  254.     int collision;   /* did the craft collide with something */
  255.     double altitude; /* altitude above surface */
  256.     double range;    /* position along surface */
  257.     double vel_x;    /* velocity x component */
  258.     double vel_y;    /* velocity y component */
  259.     double vel;      /* velocity vector */
  260.     double prev_vel; /* previous velocity - need for landing speed */
  261. } craft;
  262.  
  263. /*
  264.  * calculate the new position of the spacecraft.  "burn" is 1 if we are
  265.  * currently burning fuel, 0 if not.  we maintain a coordinate system
  266.  * using altitude and range, and convert to screen x,y coordinates.
  267.  * return value indicates whether we actually burned any fuel.
  268.  * you could probably make this function faster...
  269.  */
  270.  
  271. int compute_pos(int burn)
  272. {
  273.     double v0;
  274.     double x0;
  275.     double accel_x;
  276.     double accel_y;
  277.     int did_burn;
  278.     
  279.     /* burn some fuel if there's any left */
  280.     if (burn && craft.fuel) {
  281.     accel_x = (THRUST - GRAVITY) * cosval[craft.index];
  282.     accel_y = -(THRUST - GRAVITY) * sinval[craft.index];
  283.     --craft.fuel;
  284.     did_burn = 1;
  285.     } else {
  286.     accel_x = 0;
  287.     accel_y = -GRAVITY;
  288.     did_burn = 0;
  289.     }
  290.     
  291.     v0 = craft.vel_x;
  292.     craft.vel_x = v0 + accel_x;
  293.     x0 = craft.range;
  294.     craft.range = x0 + v0 + (accel_x/2);
  295.     if (craft.range < 0) {
  296.     /* bounce off the edge of the moon (lose some velocity) */
  297.     craft.range = 0;
  298.     craft.vel_x = -craft.vel_x/3;
  299.     accel_x = -accel_x/3;
  300.     }
  301.     else if (craft.range >= MAX_RANGE) {
  302.     craft.range = MAX_RANGE;
  303.     craft.vel_x = -craft.vel_x/3;
  304.     accel_x = -accel_x/3;
  305.     }
  306.  
  307.     v0 = craft.vel_y;
  308.     craft.vel_y = v0 + accel_y;
  309.     x0 = craft.altitude;
  310.     craft.altitude = x0 + v0 + (accel_y/2);
  311.     if (craft.altitude < 0) {
  312.     craft.altitude = 0;
  313.     craft.vel_y = 0;
  314.     accel_y = 0;
  315.     }
  316.     else if (craft.altitude >= MAX_ALTITUDE) {
  317.     craft.altitude = MAX_ALTITUDE;
  318.     craft.vel_y = 0;
  319.     }
  320.  
  321.     /* calculate velocity vector */
  322.     craft.prev_vel = craft.vel;
  323.     craft.vel = sqrt(craft.vel_x * craft.vel_x + craft.vel_y * craft.vel_y);
  324.  
  325.     /* convert lunar position to bitmap coordinates */
  326.     lem->anim->x = craft.range * bmwidth / MAX_RANGE;
  327.     lem->anim->y = (bmheight-30) - (craft.altitude * (bmheight-30) / MAX_ALTITUDE);
  328.  
  329.     return did_burn;
  330. }
  331.  
  332. /*
  333.  * collision handler for craft-to-background checks.  the pallete has been
  334.  * created such that the background colors of interest are in the third
  335.  * bitplane (colors 4,5,6,7).  we want to ignore the mountains but collide
  336.  * with the rocks on the ground, so the collision handler is enabled only
  337.  * below a certain altitude.  see the main loop for where we enable and
  338.  * disable the collision handler.
  339.  */
  340. void grounded(struct anim_struct *anim, struct coll_bg_struct *point, int color)
  341. {
  342.     craft.collision = color;
  343. }
  344.  
  345. /*
  346.  * show current stats on the control panel
  347.  */
  348. void show_stats(void)
  349. {
  350.     char cpbuf[30];
  351.     
  352.     /* update current information on the control panel */
  353.     SetAPen(&rp, 3); /* green */
  354.  
  355.     /* divide altitude and velocity by 10 for a more reasonable output */
  356.     sprintf(cpbuf, "%05d", (int)craft.altitude / 10);
  357.     Move(&rp, 22, 12);
  358.     Text(&rp, cpbuf, 5);
  359.     sprintf(cpbuf, "%05d", (int)craft.vel / 10);
  360.     Move(&rp, 85, 12);
  361.     Text(&rp, cpbuf, 5);
  362.     if (craft.fuel <= LOW_FUEL) {
  363.     SetAPen(&rp, 2); /* red */
  364.     }
  365.     sprintf(cpbuf, "%05d", (int)craft.fuel);
  366.     Move(&rp, 153, 12);
  367.     Text(&rp, cpbuf, 5);
  368.  
  369.     SetAPen(&rp, 3); /* green */
  370.     sprintf(cpbuf, "%02d:%02d", elapsed_mins, elapsed_secs);
  371.     Move(&rp, 219, 12);
  372.     Text(&rp, cpbuf, 5);
  373. }
  374.  
  375. /*
  376.  * VB interrupt handler: scroll the display when the spacecraft
  377.  * gets near one of the edges.
  378.  */
  379.  
  380. unsigned long vbcounter;
  381.  
  382. void __interrupt __saveds scroll(void)
  383. {
  384.     int dx, dy;
  385.  
  386.     ++vbcounter;
  387.     
  388.     /* keep track of elapsed time */
  389.     if (++elapsed_ticks == TICKS_PER_SEC) {
  390.     elapsed_ticks = 0;
  391.     if (++elapsed_secs == 60) {
  392.         elapsed_secs = 0;
  393.         ++elapsed_mins;
  394.     }
  395.     }
  396.     
  397.     /* keep track of when it's ok for the rock star to dance */
  398.     if (--dance_time <= 0) {
  399.     time_to_dance = 1;
  400.     dance_time = DANCE_DELAY;
  401.     }
  402.  
  403.     /* don't scroll if showing the explosion */
  404.     if (lem->seq == BOOM) {
  405.     return;
  406.     }
  407.     
  408.     if (lem->anim->x < vp.xoff + X_SCROLLPOS) {
  409.     dx = vp.xoff + X_SCROLLPOS - lem->anim->x;
  410.     } else if (lem->anim->x > vp.xoff + DWIDTH - X_SCROLLPOS) {
  411.     dx = vp.xoff + DWIDTH - X_SCROLLPOS - lem->anim->x;
  412.     } else {
  413.     dx = 0;
  414.     }
  415.  
  416.     if (lem->anim->y < vp.yoff + Y_SCROLLTOP) {
  417.     dy = vp.yoff + Y_SCROLLTOP - lem->anim->y;
  418.     } else if (lem->anim->y > vp.yoff + DHEIGHT - Y_SCROLLBOT) {
  419.     dy = vp.yoff + DHEIGHT - Y_SCROLLBOT - lem->anim->y;
  420.     } else {
  421.     dy = 0;
  422.     }
  423.  
  424.     if (dx != 0 || dy != 0) {
  425.     gs_scroll_vp(display, 0, -dx, -dy, 1);
  426.     }
  427. }
  428.  
  429.  
  430. /*
  431.  * delay specified number of vb ticks, sync with display
  432.  */
  433. void mydelay(int vbticks)
  434. {
  435.     int n = vbcounter + vbticks;
  436.     while (vbcounter < n);
  437.     while (display->flags & GSV_FLIP);    /* while page not flipped yet */
  438. }
  439.  
  440. /*
  441.  * display an error message (we should never need this)
  442.  */
  443.  
  444. struct IntuiText hdrtext = { 1,0,JAM2,10,16,NULL,NULL,NULL };
  445. struct IntuiText fataltext = { 2,0,JAM2,10,32,NULL,NULL,&hdrtext };
  446. struct IntuiText canceltext = { 1,0,JAM2,7,3,NULL,"Cancel",NULL };
  447.  
  448. void myerror(char *text)
  449. {
  450.     hdrtext.IText = "Bad news from the moon...";
  451.     fataltext.IText = text;
  452.     AutoRequest(NULL, &fataltext, NULL, &canceltext, 0, 0, 600, 90);
  453. }
  454.  
  455. /*
  456.  *  cleanup all resources and exit
  457.  */
  458.  
  459. void cleanup(void)
  460. {
  461.     gs_close_sound();
  462.     gs_free_sound(&thrust);
  463.     gs_free_sound(&whoop);
  464.     gs_free_sound(&ping);
  465.     gs_free_sound(&fill);
  466.     gs_free_sound(&kaboom);
  467.     gs_free_sound(&landed);
  468.     
  469.     if (dlist > -1) _gs_free_display_list(dlist);
  470.     if (scroller) _gs_remove_vb_server(scroller);
  471.     if (lem) gs_free_cplx(lem, 1);
  472.     if (rockstar) gs_free_cplx(rockstar, 1);
  473.     if (display) gs_remove_display(display);
  474.     /* since we allocated our own bitmaps we must free them */
  475.     if (vp.bitmap1) gs_free_bitmap(vp.bitmap1);
  476.     if (vp.bitmap2) gs_free_bitmap(vp.bitmap2);
  477.     if (vp2.bitmap1) gs_free_bitmap(vp2.bitmap1);
  478.     if (vp2.bitmap2) gs_free_bitmap(vp2.bitmap2);
  479.  
  480.     /* free up MED stuff */
  481.     if (tune) {
  482.     StopPlayer();
  483.     UnLoadModule(tune);
  484.     FreePlayer();
  485.     }
  486.     if (MEDPlayerBase) CloseLibrary(MEDPlayerBase);
  487.     
  488.     gs_close_libs();
  489.     exit(0);
  490. }
  491.  
  492.  
  493. /*
  494.  * setup all game data
  495.  */
  496.  
  497. int setup(void)
  498. {
  499.     struct anim_load_struct load = {
  500.     "lc.cplx", 0, 0, 0, 0, 8, 0, 1, ANIMLOAD_NOCOLOR
  501.     };
  502.     struct anim_load_struct loadrs = {
  503.     "rs.cplx", 0, 0, 0, 0, 8, 0, 1, ANIMLOAD_NOCOLOR
  504.     };
  505.     struct loadILBM_struct loadimg = {
  506.     "landscape.iff", 0, 0, lunar_cmap, NUM_COLORS, 0, 0, 0, 0, 0, 0, 0,
  507.     ILBM_COLOR | ILBM_ALLOC2, 0xff, 0xff
  508.     };
  509.     struct loadILBM_struct loadimg2 = {
  510.     "panel.iff", 0, 0, vp2_cmap, VP2_NUM_COLORS, 0, 0, 0, 0, 0, 0, 0,
  511.     ILBM_COLOR | ILBM_ALLOC2, 0xff, 0xff
  512.     };
  513.  
  514.     int result;
  515.     int page;
  516.     
  517.     /* open amiga libraries */
  518.     if (gs_open_libs(DOS|GRAPHICS|INTUITION|MATHDBLB|MATHDBLT|MATHTRANS,0)) {
  519.     exit(1);
  520.     }
  521.  
  522.     /* Open the MEDplayer library */
  523.     MEDPlayerBase=(struct Library *)OpenLibrary("medplayer.library",0);
  524.     if (!MEDPlayerBase) {
  525.     myerror("Need medplayer.library");
  526.     return -1;
  527.     }
  528.     
  529.     /* Load the mod */
  530.     tune = LoadModule("mod.MoonRocks");
  531.     if (!tune) {
  532.     myerror("Couldn't load mod.MoonRocks");
  533.     return -1;
  534.     }
  535.  
  536.     /* Initialize the MED player */
  537.     if (GetPlayer(0)) {
  538.     myerror("Can't Initialize MED player!");
  539.     }
  540.     
  541.     /*
  542.      * load the lunar landscape. this creates two superbitmaps for the
  543.      * double-buffered scrolling viewport, and fills in the color table
  544.      * used by all game objects.
  545.      */
  546.     result = gs_loadILBM(&loadimg);
  547.     if (result) {
  548.     myerror(loadimg.file);
  549.     return result;
  550.     }
  551.  
  552.     /* viewport will use the bitmaps just allocated */
  553.     vp.bitmap1 = loadimg.bitmap1;
  554.     vp.bitmap2 = loadimg.bitmap2;
  555.     bmwidth=vp.bitmap1->BytesPerRow*8;
  556.     bmheight=vp.bitmap1->Rows;
  557.  
  558.     /* load the control panel image */
  559.     result = gs_loadILBM(&loadimg2);
  560.     if (result) {
  561.     myerror(loadimg.file);
  562.     return result;
  563.     }
  564.     vp2.bitmap1 = loadimg2.bitmap1;
  565.     vp2.bitmap2 = loadimg2.bitmap2;
  566.     cp_bitmaps[0] = vp2.bitmap1;
  567.     cp_bitmaps[1] = vp2.bitmap2;
  568.     
  569.     /* control panel needs a RastPort so we can draw text to it */
  570.     InitRastPort(&rp);
  571.     rp.BitMap = vp2.bitmap1;
  572.     SetDrMd(&rp, JAM2);
  573.     SetBPen(&rp, 0); /* black */
  574.     
  575.     /* force topaz.8 in the control panel */
  576.     myfont = OpenFont(&sysfont);
  577.     if (!myfont) {
  578.     myerror("Can't open topaz.8 font");
  579.     return -1;
  580.     }
  581.     SetFont(&rp, myfont);
  582.  
  583.     /* load the spacecraft anim */
  584.     if (result = gs_load_anim(&load)) {
  585.     myerror(load.filename);
  586.     return result;
  587.     }
  588.     
  589.     /* get pointer to the loaded anim */
  590.     lem = load.anim_ptr.cplx;
  591.  
  592.     /* load the rock star anim */
  593.     if (result = gs_load_anim(&loadrs)) {
  594.     myerror(loadrs.filename);
  595.     return result;
  596.     }
  597.     
  598.     /* get pointer to the loaded anim */
  599.     rockstar = loadrs.anim_ptr.cplx;
  600.  
  601.     /* create the display */
  602.     #ifdef NTSC_MONITOR_ID
  603.         if (GfxBase->LibNode.lib_Version >= 36)    /* if WB 2.0 or higher */
  604.             {                    /* this defeats mode promotion on AGA machines */
  605.             if (ModeNotAvailable(NTSC_MONITOR_ID))
  606.                 {
  607.                 lunar_display.modes = PAL_MONITOR_ID;
  608.                 }
  609.             else
  610.                 {
  611.                 lunar_display.modes = NTSC_MONITOR_ID;
  612.                 }
  613.             }
  614.     #endif
  615.     result = gs_create_display(&lunar_display);
  616.     if (result) {
  617.     myerror("gs_create_display failed");
  618.     return result;
  619.     }
  620.     display = &lunar_display;
  621.     
  622.     if ((dlist=_gs_get_display_list()) < 0) {
  623.     myerror("gs_get_display_list failed");
  624.     return result;
  625.     }
  626.  
  627.     /* perform other anim initialization */
  628.     gs_init_anim(dlist,display->vp->bitmap1, display->vp->bitmap2);
  629.     gs_set_anim_bounds(dlist,0, 0, bmwidth-1, bmheight-1);
  630.     gs_random(0);
  631.  
  632.     /* setup the sound system and load the sounds */
  633.     if (gs_open_sound(0,1,-10,2560)) {
  634.     myerror("gs_open_sound failed");
  635.     return -1;
  636.     }
  637.  
  638.     /* sound of the thrusters */
  639.     thrust.flags = SND_FAST;
  640.     if (result=gs_load_iff_sound(&thrust,0,"thrust.snd")) {
  641.     myerror("cannot load thrust.snd");
  642.     return result;
  643.     }
  644.     thrust.repeat = 0; /* loop forever */
  645.     
  646.     /* low fuel alert */
  647.     whoop.flags = SND_FAST;
  648.     if (result=gs_load_iff_sound(&whoop,0,"whoop.snd")) {
  649.     myerror("cannot load whoop.snd");
  650.     return result;
  651.     }
  652.     whoop.repeat = 0; /* loop forever */
  653.     
  654.     /* a nice explosion */
  655.     kaboom.flags = SND_FAST;
  656.     if (result=gs_load_raw_sound(&kaboom,"kaboom.snd")) {
  657.     myerror("cannot load kaboom.snd");
  658.     return result;
  659.     }
  660.  
  661.     /* startrek bridge sound */
  662.     ping.flags = SND_FAST;
  663.     if (result=gs_load_raw_sound(&ping,"ping.snd")) {
  664.     myerror("cannot load ping.snd");
  665.     return result;
  666.     }
  667.     ping.repeat = 0; /* loop forever */
  668.     
  669.     /* sound played when filling the gas tank */
  670.     fill.flags = SND_FAST;
  671.     if (result=gs_load_iff_sound(&fill,0,"fill.snd")) {
  672.     myerror("cannot load fill.snd");
  673.     return result;
  674.     }
  675.     fill.repeat = 0; /* loop forever */
  676.  
  677.     /* sound played when landing is successful */
  678.     landed.flags = SND_FAST;
  679.     if (result=gs_load_iff_sound(&landed,0,"landed.snd")) {
  680.     myerror("cannot load landed.snd");
  681.     return result;
  682.     }
  683.  
  684.     /* add the anims to the display */
  685.     if (result = gs_add_anim_cplx(dlist,lem, 0, 0, lc_noflame[craft.index], 0)) {
  686.     myerror("gs_add_anim_cplx failed");
  687.     return result;
  688.     }
  689.     if (result = gs_add_anim_cplx(dlist,rockstar, 0, 0, DANCE1, 0)) {
  690.     myerror("gs_add_anim_cplx failed");
  691.     return result;
  692.     }
  693.  
  694.     gs_draw_anims(dlist);
  695.     page = gs_next_anim_page(dlist);
  696.     rp.BitMap = cp_bitmaps[page];
  697.  
  698.     /* even more anim initialization */
  699.     gs_show_display(display,1);
  700.     gs_flip_display(display,1);
  701.     
  702.     /* setup the scrolling routine */
  703.     scroller = gs_add_vb_server(&scroll, 0);
  704.     if (!scroller) {
  705.     myerror("gs_add_vb_server failed");
  706.     return -5;
  707.     }
  708.     
  709.     /* setup collision handler for things on the ground */
  710.     gs_set_collision_bg(dlist, grounded);
  711.  
  712.     return 0;
  713. }
  714.  
  715. /*
  716.  * flip to the next display page, making sure that the
  717.  * rastport bitmap for the control panel is in sync.
  718.  */
  719. void flipper(void)
  720. {
  721.     int page;
  722.  
  723.     gs_draw_anims(dlist);
  724.     page = gs_next_anim_page(dlist);
  725.     rp.BitMap = cp_bitmaps[page];
  726.     gs_flip_display(display,1);
  727. }
  728.  
  729. /*
  730.  * Start background noise - depending on whether the rock star is
  731.  * visible, it's either the startrek bridge sound, or some music.
  732.  */
  733. void start_background_noise(void)
  734. {
  735.     if (rockstar_visible) {
  736.     /* Continue playing the mod */
  737.     ContModule(tune);
  738.     } else {
  739.     gs_start_sound(&ping, PING_CHANNEL);
  740.     }
  741. }
  742.  
  743. /*
  744.  * Stop whichever background noise is playing.
  745.  */
  746. void stop_background_noise(void)
  747. {
  748.     if (rockstar_visible) {
  749.     /* Stop playing the mod */
  750.     StopPlayer();
  751.     } else {
  752.     gs_stop_sound(PING_CHANNEL);
  753.     }
  754. }
  755.  
  756. /*
  757.  * animate the dancing rock star.  time_to_dance is set in the vb interrupt
  758.  * when enough time has elapsed to do the next dance frame.  rockstar_time is
  759.  * when it's time to switch to a different dance, or when to make him
  760.  * materialize if he's currently invisible.
  761.  */
  762. void dance(void)
  763. {
  764.     if (rockstar_visible) {
  765.     /* switch to a different dance animation every once in awhile */
  766.     if (vbcounter >= rockstar_time) {
  767.         if (rockstar->seq == DANCE1) {
  768.         gs_set_cplx_seq(rockstar, DANCE2, rockstar->anim->x, rockstar->anim->y);
  769.         } else {
  770.         gs_set_cplx_seq(rockstar, DANCE1, rockstar->anim->x, rockstar->anim->y);
  771.         }
  772.         
  773.         /* switch again at a random time */
  774.         rockstar_time = vbcounter + (gs_random(5) + 5) * TICKS_PER_SEC;
  775.     }
  776.     if (time_to_dance) {
  777.         time_to_dance = 0;
  778.         gs_anim_cplx(rockstar, rockstar->anim->x, rockstar->anim->y);
  779.     }
  780.     }
  781.     else if (vbcounter >= rockstar_time && allow_rockstar) {
  782.  
  783.     /* time for him to materialize */
  784.     gs_enable_cplx(rockstar);
  785.     rockstar_visible = 1;
  786.  
  787.     /* he materializes in the reclining position and must stand up */
  788.     gs_set_cplx_seq(rockstar, STANDUP, rockstar->anim->x, rockstar->anim->y);
  789.     gs_set_cplx_cell(rockstar, 0);
  790.  
  791.     /* he'll start dancing in three seconds */
  792.     rockstar_time = vbcounter + 3 * TICKS_PER_SEC;
  793.  
  794.     /* stop the ping and start the music he'll be dancing to */
  795.     gs_stop_sound(PING_CHANNEL);
  796.     PlayModule(tune);
  797.     }
  798. }
  799.  
  800. void show_panel(int offset)
  801. {
  802.     gs_scroll_vp(display, 1, 0, offset, 1);
  803. }
  804.  
  805. /*
  806.  * user paused the game
  807.  */
  808. void pause_game(int current_panel)
  809. {
  810.     /* user pressed LMB to get here, wait for it to be released */
  811.     while (gs_joystick(0)&JOY_BUTTON1) {}
  812.  
  813.     /* scroll the control panel to show the pause display */
  814.     show_panel(VP_PAUSED - current_panel);
  815.     
  816.     /* wait for response */
  817.     while (1) {
  818.     if (gs_joystick(0) & JOY_BUTTON1) {
  819.         /* mouse button - resume game */
  820.         /* but wait for LMB to be released first */
  821.         while (gs_joystick(0)&JOY_BUTTON1) {}
  822.  
  823.         /* scroll the control panel to return to the game display */
  824.         show_panel(-VP_PAUSED + current_panel);
  825.         return;
  826.     }
  827.     if (gs_joystick(1) & JOY_BUTTON1) {
  828.         /* joystick button - quit game */
  829.         Permit();
  830.         cleanup();
  831.     }
  832.  
  833.     /* dance continues even while paused */
  834.     dance();
  835.     mydelay(1);
  836.     flipper();
  837.     }
  838. }
  839.  
  840. /*
  841.  * landed at fuel station
  842.  */
  843. void refuel(void)
  844. {
  845.     stop_background_noise();
  846.     mydelay(25);
  847.     gs_start_sound(&fill, FILL_CHANNEL);
  848.  
  849.     craft.vel_x = 0;
  850.     craft.vel_y = 0;
  851.     craft.index = 0;
  852.     gs_set_cplx_seq(lem, LEM00, lem->anim->x, lem->anim->y);
  853.  
  854.     /* fill the tank */
  855.     while (craft.fuel < MAX_FUEL) {
  856.         
  857.     craft.fuel += 3;
  858.     if (craft.fuel > MAX_FUEL) {
  859.         craft.fuel = MAX_FUEL;
  860.     }
  861.  
  862.     if (gs_joystick(0)&JOY_BUTTON1) {
  863.  
  864.         pause_game(0);
  865.     }
  866.  
  867.     show_stats();
  868.     gs_anim_cplx(lem, lem->anim->x, lem->anim->y);
  869.     dance();
  870.  
  871.     mydelay(1);
  872.     flipper();
  873.     }
  874.     gs_stop_sound(FILL_CHANNEL);
  875.     mydelay(25);
  876.     start_background_noise();
  877.  
  878.     /* wait for liftoff */
  879.     while (1) {
  880.  
  881.     if (gs_joystick(0)&JOY_BUTTON1) {
  882.  
  883.         pause_game(0);
  884.     }
  885.  
  886.     if (gs_joystick(1) & JOY_BUTTON1) {
  887.  
  888.         /* need to give the craft a good kick to get it away from the
  889.          * fuel platform.  otherwise the collision detection in the
  890.          * main loop will bring us right back here.
  891.          */
  892.         craft.altitude += 500;
  893.         craft.collision = 0;
  894.         return;
  895.     }
  896.  
  897.     /* continue page-flipping to show the clock ticking */
  898.     show_stats();
  899.     gs_anim_cplx(lem, lem->anim->x, lem->anim->y);
  900.     dance();
  901.     mydelay(1);
  902.     flipper();
  903.     }
  904.         
  905. }
  906.  
  907. /*
  908.  * spacecraft crashed into something
  909.  */
  910. void crash(void)
  911. {
  912.     int i;
  913.     
  914.     stop_background_noise();
  915.     gs_stop_sound(THRUST_CHANNEL);
  916.     gs_stop_sound(WHOOP_CHANNEL);
  917.     gs_start_sound(&kaboom, KABOOM_CHANNEL);
  918.  
  919.     /* show the crashed control panel */
  920.     show_panel(VP_CRASHED);
  921.     
  922.     /* adjust anim position because explosion is bigger than craft */
  923.     lem->anim->x -= 40;
  924.     lem->anim->y -= 20;
  925.     gs_set_cplx_seq(lem, BOOM, lem->anim->x, lem->anim->y);
  926.     gs_set_cplx_cell(lem, 0);
  927.  
  928.     /* animate the explosion for a few seconds */
  929.     for (i = 0; i < 90; i++) {
  930.         
  931.     if (gs_joystick(0)&JOY_BUTTON1) {
  932.  
  933.         pause_game(VP_CRASHED);
  934.     }
  935.     show_stats();
  936.     gs_anim_cplx(lem, lem->anim->x, lem->anim->y);
  937.     dance();
  938.         
  939.     /* explosion sequence is slower than main animation */
  940.     mydelay(5);
  941.     flipper();
  942.     }
  943.  
  944.     /* restore the main control panel */
  945.     show_panel(-VP_CRASHED);
  946.  
  947.     /* in case he appeared while we crashed... */
  948.     stop_background_noise();
  949. }
  950.  
  951. /*
  952.  * successful landing.  returns non-zero if won the game, else 0.
  953.  */
  954. int safe_landing(void)
  955. {
  956.     int panel;
  957.     int dist;
  958.     
  959.     /* wait for joystick button to be released */
  960.     while (gs_joystick(1)&JOY_BUTTON1) {}
  961.  
  962.     gs_stop_sound(THRUST_CHANNEL);
  963.     craft.vel_x = 0;
  964.     craft.vel_y = 0;
  965.     craft.index = 0;
  966.     gs_set_cplx_seq(lem, LEM00, lem->anim->x, lem->anim->y);
  967.  
  968.     /* did we land near the rock star? */
  969.     if (rockstar_visible) {
  970.  
  971.     dist = abs(rockstar->anim->x - lem->anim->x);
  972.     if (dist <= CLOSE_ENOUGH) {
  973.  
  974.         /* we have a winner! */
  975.         panel = VP_SUCCESS;
  976.         show_panel(panel);
  977.  
  978.         gs_stop_sound(WHOOP_CHANNEL);
  979.  
  980.         /* Stop playing the mod */
  981.         StopPlayer();
  982.         mydelay(5);
  983.         gs_start_sound(&landed, LANDED_CHANNEL);
  984.         mydelay(5);
  985.  
  986.         /* what for congrats to finish, then restart the mod */
  987.         while (gs_sound_check() & LANDED_CHANNEL) {}
  988.         PlayModule(tune);
  989.         
  990.     } else {
  991.  
  992.         /* didn't land close enough */
  993.         panel = VP_VISIBLE;
  994.         show_panel(panel);
  995.     }
  996.     
  997.     } else {
  998.     /* he's not even visible yet! */
  999.     panel = VP_NOWHERE;
  1000.     show_panel(panel);
  1001.     }
  1002.  
  1003.  
  1004.     /* wait for liftoff */
  1005.     while (1) {
  1006.  
  1007.     if (gs_joystick(0)&JOY_BUTTON1) {
  1008.  
  1009.         pause_game(panel);
  1010.     }
  1011.  
  1012.     if (gs_joystick(1) & JOY_BUTTON1) {
  1013.  
  1014.         craft.altitude += 300;
  1015.         craft.collision = 0;
  1016.  
  1017.         /* flip back to the main control panel */
  1018.         show_panel(-panel);
  1019.  
  1020.         /* return result of landing close */
  1021.         if (panel == VP_SUCCESS) {
  1022.         stop_background_noise();
  1023.         return 1;
  1024.         } else {
  1025.         start_background_noise();
  1026.         return 0;
  1027.         }
  1028.     }
  1029.  
  1030.     show_stats();
  1031.     gs_anim_cplx(lem, lem->anim->x, lem->anim->y);
  1032.     dance();
  1033.     mydelay(5);
  1034.     flipper();
  1035.     }
  1036. }
  1037.  
  1038. /*
  1039.  * main program:  set everything up and then play the game (duh...)
  1040.  */
  1041.  
  1042. void main(void)
  1043. {
  1044.     int result;
  1045.     unsigned char joy;
  1046.     int burn;
  1047.     int thrusting = 0;
  1048.     int joycount;
  1049.     
  1050.     /* setup the animation system */
  1051.     if ((result = setup()) != 0) {
  1052.     char err[60];
  1053.     sprintf(err, "setup failed (%d)", result);
  1054.     myerror(err);
  1055.     cleanup();
  1056.     }
  1057.  
  1058.     /* play multiple times until mouse button is pressed */
  1059.     Forbid();
  1060.     while (1) {
  1061.     
  1062.     /*
  1063.      * spacecraft begins with a full tank, at a random position and
  1064.      * velocity.  what's really cool about this is that the scroll
  1065.      * interrupt will automatically reposition the superbitmap so
  1066.      * that the spacecraft is visible.  the main loop never has
  1067.      * to care what the physical display looks like!
  1068.      */
  1069.     craft.fuel = MAX_FUEL;
  1070.     craft.altitude = MAX_ALTITUDE;
  1071.     craft.range = (gs_random(bmwidth - 200) + 100) * MAX_RANGE / bmwidth;
  1072.     craft.vel_x = gs_random(200) - 100;
  1073.     if (craft.vel_x > 0) {
  1074.         craft.index = LC_ANIM_COUNT-1;
  1075.     } else {
  1076.         craft.index = 1;
  1077.     }
  1078.     craft.vel_y = 0;
  1079.     craft.collision = 0;
  1080.     compute_pos(0);
  1081.  
  1082.     /* reset the elapsed time counter */
  1083.     elapsed_mins = 0;
  1084.     elapsed_secs = 0;
  1085.     elapsed_ticks = 0;
  1086.     
  1087.     /* place rock star at a random ground position */
  1088.     rockstar->anim->x = gs_random(bmwidth - 100) + 50;
  1089.     rockstar->anim->y = bmheight-30;
  1090.     
  1091.     /* but he's invisible for awhile */
  1092.     gs_clear_cplx(rockstar);
  1093.     rockstar_visible = 0;
  1094.     allow_rockstar = 1;
  1095.     
  1096.     /* he will materialize at a random time at least 40 seconds after
  1097.        the start of the game. */
  1098.     rockstar_time = vbcounter + (40 + gs_random(90)) * TICKS_PER_SEC;
  1099.     
  1100.     joycount = JOY_INTERVAL;
  1101.  
  1102.     show_stats();
  1103.     
  1104.     start_background_noise();
  1105.     
  1106.     /*
  1107.      * Here is the main game loop.  Simply watch the joystick and move
  1108.      * the anim around appropriately.  We continue in this inner loop
  1109.      * until we land near the target or we crash.
  1110.      */
  1111.     while (1) {
  1112.  
  1113.         if (gs_joystick(0)&JOY_BUTTON1) {
  1114.  
  1115.         pause_game(0);
  1116.         }
  1117.  
  1118.         /*
  1119.          * Check the joystick.  Left and right will rotate the spacecraft
  1120.          * 15 degrees in either direction.  Button will burn some fuel.
  1121.          */
  1122.         joy = gs_joystick(1);
  1123.         
  1124.         /*
  1125.          * Check rotational motion every JOY_INTERVAL times through this
  1126.          * loop.  If we check it too often, the spacecraft rotates too
  1127.          * fast to be playable.  Thrust button is checked every time.
  1128.          */
  1129.         if (--joycount <= 0) {
  1130.         joycount = JOY_INTERVAL;
  1131.         
  1132.         if (joy & JOY_RIGHT) {
  1133.             /* rotate clockwise */
  1134.             if (++craft.index == LC_ANIM_COUNT) craft.index = 0;
  1135.         } else if (joy & JOY_LEFT) {
  1136.             /* rotate counter-clockwise */
  1137.             if (--craft.index < 0) craft.index = LC_ANIM_COUNT-1;
  1138.         }        
  1139.         }
  1140.         
  1141.         if (joy & JOY_BUTTON1) {
  1142.         /* calculate the next spacecraft position with full throttle */
  1143.         burn = compute_pos(1);
  1144.         } else {
  1145.         /* calculate the next spacecraft position with no throttle */
  1146.         burn = compute_pos(0);
  1147.         }
  1148.         
  1149.         /* show the spacecraft with or without flame depending on whether
  1150.            we burned any fuel */
  1151.         if (burn) {
  1152.  
  1153.         /* we burned fuel this time.  show the spacecraft with flame */
  1154.         gs_set_cplx_seq(lem, lc_flame[craft.index], lem->anim->x, lem->anim->y);
  1155.         /* turn on the thrust sound if it's not already on */
  1156.         if (!thrusting) {
  1157.             thrusting = 1;
  1158.             gs_start_sound(&thrust, THRUST_CHANNEL);
  1159.         }
  1160.  
  1161.         if (craft.fuel == LOW_FUEL) {
  1162.             /* we're running on fumes! */
  1163.             gs_start_sound(&whoop, WHOOP_CHANNEL);
  1164.         } else if (craft.fuel == 0) {
  1165.             /* not even any fumes left! */
  1166.             gs_stop_sound(WHOOP_CHANNEL);
  1167.             gs_stop_sound(THRUST_CHANNEL);
  1168.             stop_background_noise();
  1169.             thrusting = 0;
  1170.         }
  1171.         
  1172.         } else {
  1173.         /* no fuel burned this time, show spacecraft without flame */
  1174.         gs_set_cplx_seq(lem, lc_noflame[craft.index], lem->anim->x, lem->anim->y);
  1175.         /* turn off thrust sound if necessary */
  1176.         if (thrusting) {
  1177.             gs_stop_sound(THRUST_CHANNEL);
  1178.             thrusting = 0;
  1179.         }
  1180.         }
  1181.     
  1182.         /* we want background collision checking to occur only when the
  1183.          * spacecraft is near the bottom of the bitmap (i.e. it can crash
  1184.          * into the rocks on the ground but not the mountains in the
  1185.          * distance).  we check the ANIM_COLLISION_BG bit in the flags
  1186.          * so that we enable or disable collision checking only once
  1187.          * each time we cross the threshold.
  1188.          */
  1189.         if (lem->anim->y > GROUND_THRESHOLD && !(lem->anim->flags & ANIM_COLLISION_BG)) {
  1190.         gs_enable_cplx_collision_bg(lem);
  1191.         } else if (lem->anim->y <= GROUND_THRESHOLD && (lem->anim->flags & ANIM_COLLISION_BG)) {
  1192.         gs_disable_cplx_collision_bg(lem);
  1193.         }
  1194.  
  1195.         /* show current stats */
  1196.         show_stats();
  1197.  
  1198.         /* show the next spacecraft animation frame as determined above */
  1199.         gs_anim_cplx(lem, lem->anim->x, lem->anim->y);
  1200.         
  1201.         /* rock star is dancing */
  1202.         dance();
  1203.         
  1204.         /* update the off-screen bitmap, then display it */
  1205.         mydelay(1);
  1206.         flipper();
  1207.  
  1208.         /* if we landed on the fuel platform, fill 'er up */
  1209.         /* this happens if collide with background color white or yellow */
  1210.         /* make sure landed slowly and more-or-less upright */
  1211.         if (craft.collision == 5 || craft.collision == 6) {
  1212.  
  1213.         if (craft.prev_vel <= SAFE_SPEED &&
  1214.             (craft.index == 0 || craft.index == 1 || craft.index == LC_ANIM_COUNT-1)) {
  1215.             /* landed on platform ok */
  1216.             if (craft.fuel < MAX_FUEL) {
  1217.             gs_stop_sound(THRUST_CHANNEL);
  1218.             thrusting = 0;
  1219.             refuel();
  1220.             }
  1221.         } else {
  1222.             /* crashed on platform */
  1223.             crash();
  1224.             break;
  1225.         }
  1226.         } else if (craft.collision) {
  1227.         /* collided with a rock */
  1228.         crash();
  1229.         break;
  1230.         } else if (craft.altitude == 0) {
  1231.         /* on the ground, let's see how we landed */
  1232.         gs_stop_sound(THRUST_CHANNEL);
  1233.         gs_stop_sound(WHOOP_CHANNEL);
  1234.  
  1235.         /* don't let rock star appear nearby if he's not visible yet */
  1236.         if (!rockstar_visible) {
  1237.             gs_stop_sound(PING_CHANNEL);
  1238.             allow_rockstar = 0;
  1239.         }
  1240.         
  1241.         craft.vel = 0;
  1242.         mydelay(2);
  1243.  
  1244.         if (craft.prev_vel <= SAFE_SPEED &&
  1245.             (craft.index == 0 || craft.index == 1 || craft.index == LC_ANIM_COUNT-1)) {
  1246.             /* a gentle upright landing! */
  1247.             thrusting = 0;
  1248.             if (safe_landing()) {
  1249.             /* won the game, start over */
  1250.             break;
  1251.             }
  1252.             /* otherwise continue the search */
  1253.             allow_rockstar = 1;
  1254.  
  1255.             /* if we sat on the ground waiting for him to appear,
  1256.                don't let him appear right away */
  1257.             if (!rockstar_visible) {
  1258.             rockstar_time = vbcounter + (gs_random(5) + 20) * TICKS_PER_SEC;
  1259.             }
  1260.         } else {
  1261.             /* too fast or tilted or hit a rock */
  1262.             crash();
  1263.             break;
  1264.         }
  1265.         }
  1266.     }
  1267.     }
  1268. }
  1269.  
  1270.